package com.wjk.cms.util.lottery;

import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

@Slf4j
public class LotteryGame {

    String type;

    List<LotteryGameItem> lotteryGameItems;

    Map<Integer, String> pool;

    int poolSize;

    Map<String, LotteryGameItem> itemMap;

    String detail;

    public LotteryGame(String type, List<LotteryGameItem> lotteryGameItems) {
        this.type = type;
        this.lotteryGameItems = lotteryGameItems;
    }

    public void init() {
        pool = new LinkedHashMap<>();
        itemMap = new HashMap<>();
        if (!"0".equals(type)) {
            lotteryGameItems.stream().forEach(lotteryGameItem -> lotteryGameItem.setProbability(lotteryGameItem.getRemaining()));
        }
        lotteryGameItems.sort(new Comparator<LotteryGameItem>() {
            @Override
            public int compare(LotteryGameItem o1, LotteryGameItem o2) {
                return o1.getProbability() - o2.getProbability();
            }
        });
        int p = 0;
        poolSize = 0;
        for (LotteryGameItem item : lotteryGameItems) {
            p += item.getProbability();
            poolSize += item.getRemaining();
            pool.put(p, item.getIdentifier());
            itemMap.put(item.getIdentifier(), item);
        }
        log.info(getPoolDebugInfo());
    }

    String getPoolDebugInfo() {
        StringBuilder sb = new StringBuilder();
        sb.append("抽奖奖池\n");
        for (Map.Entry<Integer, String> entry : pool.entrySet()) {
            LotteryGameItem item = itemMap.get(entry.getValue());
            sb.append("高度: " + entry.getKey() + ", 奖品: " + entry.getValue() + " (" + getItemDebugInfo(item) + ")\n");
        }
        return sb.toString();
    }

    String getItemDebugInfo(LotteryGameItem item) {
        return "描述: " + item.getDescription() + ", 概率: " + item.getProbability() + "/万, 剩余: " + (item.getRemaining() >= 0 ? item.getRemaining() : "无限");
    }

    public static void main0(String[] args) {
        List<LotteryGameItem> items = new ArrayList<>();
        items.add(new LotteryGameItemVO("1", 100, 1, "红包888")); // 1(1)
        items.add(new LotteryGameItemVO("2", 400, 5, "红包100")); // 4(5)
        items.add(new LotteryGameItemVO("3", 500, 10, "红包50")); // 5(10)
        items.add(new LotteryGameItemVO("4", 1000, 100, "红包20")); // 10(20)
        items.add(new LotteryGameItemVO("5", 2000, 200, "红包10")); // 20(40)
        items.add(new LotteryGameItemVO("6", 6000, -1, "红包5")); // 60(100)
        LotteryGame lotteryGame = new LotteryGame("0", items);
        lotteryGame.init();
        int times = 1000;
        for (int i = 0; i < times; i++) {
            log.info("第" + (i + 1) + "次");
            String result = lotteryGame.draw();
            if (result != null) {
                lotteryGame.getItem(result).decRemaining();
            }
        }
    }

    LotteryGameItem getItem(String identifier) {
        return itemMap.get(identifier);
    }

    public String getDetail() {
        return detail;
    }

    public static void main(String[] args) {
        List<LotteryGameItem> items = new ArrayList<>();
        LotteryGame lotteryGame = new LotteryGame("1", items);
        lotteryGame.init();
        String result = lotteryGame.draw();
    }

    public String draw() {
        if (pool.isEmpty() || poolSize == 0) {
            detail = "奖池为空";
            return null;
        }
        int bound = "0".equals(type) ? 10000 : poolSize;
        int random = ThreadLocalRandom.current().nextInt(bound) + 1;
        StringBuilder sb = new StringBuilder();
        sb.append("抽奖结果\n随机高度: " + random + "\n");
        for (Map.Entry<Integer, String> entry : pool.entrySet()) {
            sb.append("匹配奖品高度: " + entry.getKey() + ", 匹配结果: ");
            if (random <= entry.getKey()) {
                sb.append("中 - " + getItemDebugInfo(itemMap.get(entry.getValue())));
                if (itemMap.get(entry.getValue()).getRemaining() != 0) {
                    sb.append("\n");
                    detail = sb.toString();
                    log.info(detail);
                    return entry.getValue();
                } else {
                    sb.append(", 奖品无剩余");
                }
                sb.append("\n");
            } else {
                sb.append("不中 - " + getItemDebugInfo(itemMap.get(entry.getValue())) + "\n");
            }
        }
        //sb.append("奖池奖品不足!\n");
        detail = sb.toString();
        log.info(detail);
        return null;
    }

}
